//===----------------------------------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// GLKit overlays for Swift
//===----------------------------------------------------------------------===//

@_exported import GLKit // Clang module

// The GLKit headers provide a fairly complete set of types and operations
// that Swift's importer is now able to present in Swift. However, Swift
// still doesn't know yet how to natively expose the elements of these types.
// This overlay generates Swift accessors for the GLKit matrix and vector
// types.

// Do dirty pointer manipulations to index an opaque struct like an array.
@inlinable // FIXME(inline-always)
@inline(__always)
public func _indexHomogeneousValue<TTT, T>(_ aggregate: UnsafePointer<TTT>,
                                           _ index: Int) -> T {
  return UnsafeRawPointer(aggregate).load(
    fromByteOffset: index * MemoryLayout<T>.stride, as: T.self)
}

%{
def defineSubscript(Type, limit):
  return """
  @inlinable // FIXME(inline-always)
  public subscript(i: Int) -> Float {{
    @inline(__always)
    get {{
      precondition(i >= 0, "Negative {0} index out of range")
      precondition(i < {1}, "{0} index out of range")

      // We can't derive an UnsafePointer from a let binding. Lame.
      var clone = self
      return _indexHomogeneousValue(&clone, i)
    }}
  }}
  """.format(Type, limit)
}%

% for size in [2, 3, 4]:

extension GLKMatrix${size} {
  ${ defineSubscript("GLKMatrix" + str(size), size * size) }
}

extension GLKVector${size} {
  ${ defineSubscript("GLKVector" + str(size), size) }
}

% end

extension GLKQuaternion {
  ${ defineSubscript("GLKQuaternion", 4) }
}
